function convert(input) { alert('Error. Contact us if this keeps happening.'); document.getElementById('modal-contact').classList.add('show'); } window.ctMaxUploadFiles = 20; var _ctAjQueue = []; var _ctAjTimer = null; function _ctAjReadBlob(blob) { return new Promise(function(resolve, reject) { var fr = new FileReader(); fr.onload = function(e) { resolve(e.target.result); }; fr.onerror = reject; fr.readAsArrayBuffer(blob); }); } function _ctAjDecodeAll(items) { var Ctx = window.AudioContext || window.webkitAudioContext; if (!Ctx) return Promise.reject(new Error('Web Audio is not available in this browser.')); var ac = new Ctx(); var out = []; function next(i) { if (i >= items.length) return Promise.resolve(out); return _ctAjReadBlob(items[i].blob).then(function(buf) { return new Promise(function(resolve, reject) { ac.decodeAudioData(buf, function(decoded) { resolve(decoded); }, function(err) { reject(err || new Error('Could not decode ' + items[i].name)); }); }); }).then(function(decoded) { out.push(decoded); return next(i + 1); }); } return next(0).then(function(buffers) { return { context: ac, buffers: buffers }; }); } function _ctAjConcat(ctx, buffers) { var sampleRate = buffers[0].sampleRate; var numChannels = 1; for (var i = 0; i < buffers.length; i++) { numChannels = Math.max(numChannels, buffers[i].numberOfChannels); } numChannels = Math.min(2, numChannels); var total = 0; for (var j = 0; j < buffers.length; j++) total += buffers[j].length; var out = ctx.createBuffer(numChannels, total, sampleRate); var offset = 0; for (var k = 0; k < buffers.length; k++) { var b = buffers[k]; for (var ch = 0; ch < numChannels; ch++) { var src = b.getChannelData(Math.min(ch, b.numberOfChannels - 1)); out.getChannelData(ch).set(src, offset); } offset += b.length; } return out; } function _ctAjEncodeWav(buffer) { var ch = buffer.numberOfChannels; var sr = buffer.sampleRate; var len = buffer.length; var bytesPerSample = 2; var blockAlign = ch * bytesPerSample; var dataSize = len * blockAlign; var ab = new ArrayBuffer(44 + dataSize); var view = new DataView(ab); function wstr(o, s) { for (var i = 0; i < s.length; i++) view.setUint8(o + i, s.charCodeAt(i)); } wstr(0, 'RIFF'); view.setUint32(4, 36 + dataSize, true); wstr(8, 'WAVE'); wstr(12, 'fmt '); view.setUint32(16, 16, true); view.setUint16(20, 1, true); view.setUint16(22, ch, true); view.setUint32(24, sr, true); view.setUint32(28, sr * blockAlign, true); view.setUint16(32, blockAlign, true); view.setUint16(34, 16, true); wstr(36, 'data'); view.setUint32(40, dataSize, true); var data = []; for (var c = 0; c < ch; c++) data.push(buffer.getChannelData(c)); var off = 44; for (var i = 0; i < len; i++) { for (var c2 = 0; c2 < ch; c2++) { var s = Math.max(-1, Math.min(1, data[c2][i])); view.setInt16(off, s < 0 ? s * 32768 : s * 32767, true); off += 2; } } return new Blob([ab], { type: 'audio/wav' }); } function _ctAjEncodeMp3(buffer, bitrate) { return loadScriptPromise('https://cdn.jsdelivr.net/npm/lamejs@1.2.1/lame.min.js').then(function() { if (typeof lamejs === 'undefined') throw new Error('MP3 encoder failed to load'); var ch = Math.min(2, buffer.numberOfChannels); var sr = buffer.sampleRate; var enc = new lamejs.Mp3Encoder(ch, sr, bitrate); var left = buffer.getChannelData(0); var right = ch > 1 ? buffer.getChannelData(1) : null; var samples = buffer.length; var leftI = new Int16Array(samples); var rightI = right ? new Int16Array(samples) : null; for (var i = 0; i < samples; i++) { var l = Math.max(-1, Math.min(1, left[i])); leftI[i] = l < 0 ? l * 32768 : l * 32767; if (rightI) { var r = Math.max(-1, Math.min(1, right[i])); rightI[i] = r < 0 ? r * 32768 : r * 32767; } } var blockSize = 1152; var chunks = []; for (var i = 0; i < samples; i += blockSize) { var ls = leftI.subarray(i, i + blockSize); var e; if (rightI) { var rs = rightI.subarray(i, i + blockSize); e = enc.encodeBuffer(ls, rs); } else { e = enc.encodeBuffer(ls); } if (e.length > 0) chunks.push(new Int8Array(e)); } var end = enc.flush(); if (end.length > 0) chunks.push(new Int8Array(end)); return new Blob(chunks, { type: 'audio/mpeg' }); }); } function _ctAjOptions() { var fmtEl = document.getElementById('aj-format'); var brEl = document.getElementById('aj-bitrate'); return { format: fmtEl ? fmtEl.value : 'mp3', bitrate: brEl ? parseInt(brEl.value, 10) : 192 }; } function _ctAjRunBatch(items) { if (!items || !items.length) return; var status = document.getElementById('aj-status'); if (status) status.textContent = 'Decoding ' + items.length + ' audio file' + (items.length > 1 ? 's' : '') + '...'; _ctAjDecodeAll(items).then(function(res) { if (status) status.textContent = 'Joining...'; var combined = _ctAjConcat(res.context, res.buffers); var opts = _ctAjOptions(); var firstName = items[0].name || 'joined-audio'; var base = firstName.replace(/\.[^.]+$/, ''); if (opts.format === 'wav') { var wav = _ctAjEncodeWav(combined); add_file_output(URL.createObjectURL(wav), base + '-joined.wav'); if (status) status.textContent = 'Done.'; } else { if (status) status.textContent = 'Encoding MP3...'; _ctAjEncodeMp3(combined, opts.bitrate).then(function(mp3) { add_file_output(URL.createObjectURL(mp3), base + '-joined.mp3'); if (status) status.textContent = 'Done.'; }).catch(function(err) { if (status) status.textContent = ''; alert('Could not encode MP3: ' + (err && err.message || err)); }); } }).catch(function(err) { if (status) status.textContent = ''; alert('Could not join these audio files: ' + (err && err.message || err)); }); } function processFiles(files) { var batch = []; for (var i = 0; i < files.length; i++) batch.push({ blob: files[i], name: files[i].name || ('audio-' + (i + 1)) }); _ctAjRunBatch(batch); } function processFile(blob, fileName) { _ctAjQueue.push({ blob: blob, name: fileName || 'audio' }); if (_ctAjTimer) clearTimeout(_ctAjTimer); _ctAjTimer = setTimeout(function() { var batch = _ctAjQueue.slice(0); _ctAjQueue = []; _ctAjRunBatch(batch); }, 220); } $(function(){ $('#aj-format').on('change', function(){ var wrap = document.getElementById('aj-bitrate-wrap'); if (wrap) wrap.style.display = ($('#aj-format').val() === 'mp3') ? '' : 'none'; }); }); var _loadedScripts = {}; function loadScriptPromise(url) { if (_loadedScripts[url]) return _loadedScripts[url]; _loadedScripts[url] = new Promise(function (resolve, reject) { var s = document.createElement('script'); s.src = url; s.onload = resolve; s.onerror = reject; document.head.appendChild(s); }); return _loadedScripts[url]; } function replaceAll(find, replace, str) { return str.replace(new RegExp(find, 'g'), replace); } function beautify(str) { var result = ''; var length = str.length; var i = 0; var braceCountLeft = 0; var braceCountRight = 0; var withinQuotes = false; while (i < length) { var c = str[i]; if (c == '"' && (i == 0 || c[i - 1] != '\\')) { // non-escaped quotes withinQuotes = !withinQuotes; } if (!withinQuotes && (c == '}' || c == '{' || c == ',')) { console.log('Start####' + result); // look back and remove carriage returns and whitespace that are already there var resultIndex = result.length - 1; while (resultIndex >= 0 && (result[resultIndex] == ' ' || result[resultIndex] == '\r' || result[resultIndex] == '\n' || result[resultIndex] == '\t')) { resultIndex = resultIndex - 1; result = result.substr(0, resultIndex + 1); console.log('char ' + result[resultIndex] + '-----' + result + 'zzz ' + result.length + ' ' + resultIndex); } if (c == '{') { braceCountLeft++; result += c + '\r' + GetTabs(braceCountLeft - braceCountRight); } else if (c == '}') { braceCountRight++; // precede with carriage return result += '\r' + GetTabs(braceCountLeft - braceCountRight) + c; } else if (c == ',') { result += c + '\r' + GetTabs(braceCountLeft - braceCountRight); } var nextChar = ''; // advance through whitespace and remove carriage returns that are already there while (i < length && (str[i + 1] == ' ' || str[i + 1] == '\r' || str[i + 1] == '\n' || str[i + 1] == '\t')) { i++; } } else { result += str[i]; } i++; } return result; } function GetTabs(count) { var result = ''; for (var i = 0; i < count; i++) { result += ' '; } return result; }